home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Add-Ons / MPW / MPW fixit / fixit.y < prev    next >
Encoding:
Lex Description  |  1996-07-08  |  8.5 KB  |  379 lines  |  [TEXT/MPS ]

  1. %{
  2.  
  3. /* File fixit.y Copyright (C) 1996 by John R. Montbriand.  All Rights Reserved. */
  4.  
  5. /* File fixit.y
  6.  
  7.     Copyright (C) 1996 by John Montbriand.  All Rights Reserved.
  8.     
  9.     Distribute freely in areas where the laws of copyright apply.
  10.     
  11.     Use at your own risk.
  12.     
  13.     Do not distribute modified copies.
  14.     
  15.     These various fixmath routines and libraries are for free!
  16.     
  17.     See the file fixit.txt for details.
  18.     
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <string.h>
  24. #include <ToolUtils.h>
  25. #include "fixit.h"
  26.  
  27. void yyerror(char*);
  28.  
  29. typedef enum {
  30.     kAdd,
  31.     kSubtract,
  32.     kMultiply,
  33.     kDivide,
  34.     kExponent,
  35.     kSine,
  36.     kCosine,
  37.     kTangent,
  38.     kSquare,
  39.     kSquareRoot,
  40.     kNegate,
  41.     kIdentifier,
  42.     kConstant
  43. } NodeKind;
  44.  
  45. #define kTableSize 200
  46. #define kStringTableSize 512
  47.  
  48. typedef struct FixedNode {
  49.     NodeKind kind;
  50.     char *name;
  51.     Fixed value;
  52.     long arg_one;
  53.     long arg_two;
  54. } FixedNode;
  55.  
  56. long addoperator(NodeKind kind, long a, long b);
  57. long addidentifier(char* id);
  58. long addconstant(Fixed n);
  59.  
  60. void SimplifyTree(long *root);
  61. long PrintTree(long root);
  62.  
  63. FixedNode gTable[kTableSize];
  64. long gTableP = kTableSize;
  65. char gStringTable[kStringTableSize], *gStringP;
  66.  
  67.  
  68. %}
  69.  
  70. %start  statement
  71.  
  72. %token NUMBER IDENTIFIER EXPONENT SINE COSINE TANGENT SQUARE SQUARE_ROOT 
  73.  
  74. %left '+' '-'
  75. %left '*' '/'
  76. %left EXPONENT
  77. %left UMINUS      /*  supplies  precedence  for  unary  minus  */
  78.  
  79. %%      /*  beginning  of  rules  section  */
  80.  
  81. statement : 
  82.     expr
  83.         {    long root;
  84.             root = $1;
  85.             SimplifyTree(&root);
  86.             $$ = PrintTree(root);
  87.         }
  88.      ;
  89.  
  90. expr :    '('  expr  ')'
  91.         {    $$  =  $2;  }
  92.     | expr  '+'  expr
  93.         {    $$  =  addoperator(kAdd, $1, $3);  }
  94.     | expr  '-'  expr
  95.         {    $$  =  addoperator(kSubtract, $1, $3);  }
  96.     | expr  '*'  expr
  97.         {    $$  =  addoperator(kMultiply, $1, $3);  }
  98.     | expr  '/'  expr
  99.         {    $$  =  addoperator(kDivide, $1, $3);  }
  100.     | expr  EXPONENT  expr
  101.         {    $$  =  addoperator(kExponent, $1, $3);  }
  102.     | SINE '(' expr ')'
  103.         {    $$  =  addoperator(kSine, $3, 0);  }
  104.     | COSINE '(' expr ')'
  105.         {    $$  =  addoperator(kCosine, $3, 0);  }
  106.     | TANGENT '(' expr ')'
  107.         {    $$  =  addoperator(kTangent, $3, 0);  }
  108.     | SQUARE '(' expr ')'
  109.         {    $$  =  addoperator(kSquare, $3, 0);  }
  110.     | SQUARE_ROOT '(' expr ')'
  111.         {    $$  =  addoperator(kSquareRoot, $3, 0);  }
  112.     | '-'    expr    %prec  UMINUS
  113.         {    $$  =  addoperator(kNegate, $2, 0);  }
  114.     | IDENTIFIER
  115.         {    $$  =  addidentifier((char*)$1);  }
  116.     | NUMBER
  117.         {    $$ = addconstant($1); }
  118.      ;
  119.  
  120. %%      /*  start  of  programs  */
  121.  
  122.  
  123. long addoperator(NodeKind kind, long a, long b) {
  124.     FixedNode *newnode;
  125.     if (gTableP == 0) yyerror("expression too complex");
  126.     newnode = gTable + (--gTableP);
  127.     newnode->kind = kind;
  128.     newnode->arg_one = a;
  129.     newnode->arg_two = b;
  130.     return gTableP;
  131. }
  132.  
  133. long addidentifier(char* id) {
  134.     long bytecount;
  135.     FixedNode *newnode;
  136.     bytecount = strlen(id) + 1;
  137.     if (gStringP - bytecount < gStringTable)
  138.         yyerror("String Table Exhausted");
  139.     gStringP -= bytecount;
  140.     if (gTableP == 0) yyerror("expression too complex");
  141.     newnode = gTable + (--gTableP);
  142.     newnode->kind = kIdentifier;
  143.     newnode->name = strcpy(gStringP, id);
  144.     return gTableP;
  145. }
  146.  
  147. long addconstant(Fixed n) {
  148.     FixedNode *newnode;
  149.     if (gTableP == 0) yyerror("expression too complex");
  150.     newnode = gTable + (--gTableP);
  151.     newnode->kind = kConstant;
  152.     newnode->value = n;
  153.     return gTableP;
  154. }
  155.  
  156. Boolean IsConstant(long node_num, Fixed* value) {
  157.     FixedNode *thenode;
  158.     thenode = gTable + node_num;
  159.     if (thenode->kind == kConstant) {
  160.         *value = thenode->value;
  161.         return true;
  162.     } else return false;
  163. }
  164.  
  165. void SimplifyTree(long *root) {
  166.     FixedNode *node;
  167.     Fixed a, b;
  168.     node = gTable + (*root);
  169.     switch (node->kind) {
  170.     
  171.             /* binary operators */
  172.         case kAdd:
  173.             SimplifyTree(&node->arg_one);
  174.             SimplifyTree(&node->arg_two);
  175.             if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
  176.                 *root = addconstant(a + b);
  177.             break;
  178.         case kSubtract:
  179.             SimplifyTree(&node->arg_one);
  180.             SimplifyTree(&node->arg_two);
  181.             if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
  182.                 *root = addconstant(a - b);
  183.             break;
  184.         case kMultiply:
  185.             SimplifyTree(&node->arg_one);
  186.             SimplifyTree(&node->arg_two);
  187.             if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
  188.                 *root = addconstant(FixMul(a, b));
  189.             break;
  190.         case kDivide:
  191.             SimplifyTree(&node->arg_one);
  192.             SimplifyTree(&node->arg_two);
  193.             if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
  194.                 *root = addconstant(FixDiv(a, b));
  195.             break;
  196.         case kExponent:
  197.             SimplifyTree(&node->arg_one);
  198.             SimplifyTree(&node->arg_two);
  199.             if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
  200.                 *root = addconstant(FixExp(a, b));
  201.             break;
  202.             
  203.             /* unary operators */
  204.         case kSine:
  205.             SimplifyTree(&node->arg_one);
  206.             if (IsConstant(node->arg_one, &a))
  207.                 *root = addconstant(FixSin(a));
  208.             break;
  209.         case kCosine:
  210.             SimplifyTree(&node->arg_one);
  211.             if (IsConstant(node->arg_one, &a))
  212.                 *root = addconstant(FixCos(a));
  213.             break;
  214.         case kTangent:
  215.             SimplifyTree(&node->arg_one);
  216.             if (IsConstant(node->arg_one, &a))
  217.                 *root = addconstant(FixTan(a));
  218.             break;
  219.         case kSquare:
  220.             SimplifyTree(&node->arg_one);
  221.             if (IsConstant(node->arg_one, &a))
  222.                 *root = addconstant(FixSquare(a));
  223.             break;
  224.         case kSquareRoot:
  225.             SimplifyTree(&node->arg_one);
  226.             if (IsConstant(node->arg_one, &a))
  227.                 *root = addconstant(FixSqrt(a));
  228.             break;
  229.         case kNegate:
  230.             SimplifyTree(&node->arg_one);
  231.             if (IsConstant(node->arg_one, &a))
  232.                 *root = addconstant( - a );
  233.             break;
  234.  
  235.             /* atoms */
  236.         case kIdentifier:
  237.             break;
  238.         case kConstant:
  239.             break;
  240.     }
  241. }
  242.  
  243.  
  244. long PrintTree(long root) {
  245.     FixedNode *node;
  246.     node = gTable + root;
  247.     switch (node->kind) {
  248.     
  249.             /* binary operators */
  250.         case kAdd:
  251.             printf("(");
  252.             PrintTree(node->arg_one);
  253.             printf(" + ");
  254.             PrintTree(node->arg_two);
  255.             printf(")");
  256.             break;
  257.         case kSubtract:
  258.             printf("(");
  259.             PrintTree(node->arg_one);
  260.             printf(" - ");
  261.             PrintTree(node->arg_two);
  262.             printf(")");
  263.             break;
  264.         case kMultiply:
  265.             printf("FixMul(");
  266.             PrintTree(node->arg_one);
  267.             printf(", ");
  268.             PrintTree(node->arg_two);
  269.             printf(")");
  270.             break;
  271.         case kDivide:
  272.             printf("FixDiv(");
  273.             PrintTree(node->arg_one);
  274.             printf(", ");
  275.             PrintTree(node->arg_two);
  276.             printf(")");
  277.             break;
  278.         case kExponent:
  279.             printf("FixExp(");
  280.             PrintTree(node->arg_one);
  281.             printf(", ");
  282.             PrintTree(node->arg_two);
  283.             printf(")");
  284.             break;
  285.             
  286.             /* unary operators */
  287.         case kSine:
  288.             printf("FixSin(");
  289.             PrintTree(node->arg_one);
  290.             printf(")");
  291.             break;
  292.         case kCosine:
  293.             printf("FixCos(");
  294.             PrintTree(node->arg_one);
  295.             printf(")");
  296.             break;
  297.         case kTangent:
  298.             printf("FixTan(");
  299.             PrintTree(node->arg_one);
  300.             printf(")");
  301.             break;
  302.         case kSquare:
  303.             printf("FixSquare(");
  304.             PrintTree(node->arg_one);
  305.             printf(")");
  306.             break;
  307.         case kSquareRoot:
  308.             printf("FixSqrt(");
  309.             PrintTree(node->arg_one);
  310.             printf(")");
  311.             break;
  312.         case kNegate:
  313.             printf("( - (");
  314.             PrintTree(node->arg_one);
  315.             printf(") )");
  316.             break;
  317.  
  318.             /* atoms */
  319.         case kIdentifier:
  320.             printf(node->name);
  321.             break;
  322.         case kConstant:
  323.             printf("0x%.8X", node->value);
  324.             break;
  325.     }
  326.     return 0;
  327. }
  328.  
  329.  
  330. /* y y e r r o r */
  331.  
  332. void yyerror(char* s) {
  333.     fprintf( stderr, "%s\n", s );
  334. }
  335.  
  336. char* helpmsgs[] = {
  337.     "# Tool fixit Copyright (C) 1996 by John R. Montbriand.  All Rights Reserved. ",
  338.     "# fixit reads from standard input and takes no parameters\n",
  339.     "# fixit, compiles infix expressions into fixmath calls for fixed math\n",
  340.     "# calculations.  expressions are:\n",
  341.     "#     (  expression  )            -- parentheses\n",
  342.     "#     expression  +  expression    -- addition\n",
  343.     "#     expression  -  expression    -- subtraction\n",
  344.     "#     expression  *  expression    -- multiplication (FixMul)\n",
  345.     "#     expression  /  expression    -- division (FixDiv)\n",
  346.     "#     expression  &  expression    -- logical binary and\n",
  347.     "#     expression  |  expression    -- logical binary or\n",
  348.     "#     expression  **  expression    -- exponent (FixExp)\n",
  349.     "#     sin ( expression )            -- sine (FixSin)\n",
  350.     "#     cos ( expression )            -- cosine (FixCos)\n",
  351.     "#     tan ( expression )            -- tangent (FixTan)\n",
  352.     "#     sqr ( expression )            -- square = FixMul(a, a)\n",
  353.     "#     sqrt ( expression )            -- square root (FixSqrt)\n",
  354.     "#     - expression                -- negate\n",
  355.     "#     an identifier                -- variable names\n",
  356.     "#     a number (eg. 4, 4.5, 3.14)    -- constant values\n"
  357. };
  358.  
  359. #define kHelpMsgs (sizeof(helpmsgs)/sizeof(char*))
  360.  
  361. void DrawHelp(void) {
  362.     long i;
  363.     for (i=0; i<kHelpMsgs; i++) printf("%s", helpmsgs[i]);
  364. }
  365.  
  366.  
  367. int main(long argc, char** argv) {
  368.     if (argc == 2) {
  369.         DrawHelp();
  370.         return 0;
  371.     } else {
  372.         gStringP = gStringTable + kStringTableSize;
  373.         gTableP = kTableSize;
  374.         return( yyparse() ); /* call y y p a r s e */
  375.     }
  376. }
  377.  
  378. /* end of file fixit.y */
  379.